<?php


namespace app\admin\model;


use app\common\model\TimeModel;
use app\wechat\service\WepayService;
use think\facade\Db;
use think\facade\Log;
use think\Model;

/**
 * Class UserRecharge
 * @package app\admin\model
 * Author FashionJune
 */
class UserRecharge extends TimeModel
{

    public function user()
    {
        return $this->belongsTo('app\admin\model\UserBase', 'user_id', 'id');
    }

//    public function product()
//    {
//        return $this->belongsTo('app\admin\model\ProductBase', 'product_id', 'id');
//    }

//    public function change()
//    {
//        return $this->belongsTo('app\admin\model\UserChangeType', 'change_type', 'id');
//    }

    /**
     * @param string $status
     * @return string|string[]
     * @author FashionJune
     * @title 获取订单状态
     */
    public static function getStatus($status = 'all')
    {
        $arr = [-1 => '已失败', 1 => '待支付', 2 => '已充值', 3 => '退款中', 4 => '已退款'];
        if ($status === 'all') {
            return $arr;
        } elseif ($status === 'edit') {
            unset($arr[0]);
            return $arr;
        } elseif (in_array($status, $arr)) {
            return $arr[$status];
        } else {
            return '';
        }
    }

    /**
     * @param mixed $prefix
     * @return string
     * @throws \Exception
     * @author FashionJune
     * @title 创建订单号
     */
    private function create_sn($prefix = null)
    {
        $prefix = $prefix ?? config('app.recharge.sn_prefix') ?? 'R';
        $time = date('YmdHis');
        $rand = random_int('1000', '9999');
        return $prefix . $time . $rand;
    }

    /**
     * @param Model $model
     * @return mixed|void
     * @author FashionJune
     * @title 写入前自动完成
     */
    public static function onBeforeWrite(Model $model)
    {
        if (isset($model->end_time)) {
            $model->end_time = strtotime($model->end_time);
        }
    }

    public static function onAfterRead(Model $model)
    {
        if (isset($model->change_type)) {//充值类型id变文字
            $model->type_name = UserChangeType::getTitleById($model->change_type);
        }
        if (isset($model->status)) {//渲染状态值
            $color = [-1 => '#222831', 1 => '#a20a0a', 2 => '#5aa469', 3 => '#db6400', 4 => '#070d59'];
            $status_arr = self::getStatus();
            $model->status_info = "<span style='color:" . $color[$model->status] . ";font-weight:bolder '>" . $status_arr[$model->status] . "</span>";
        }
    }

    /**
     * @title 根据订单号查询订单
     * @param string $order_sn
     * @param mixed $field
     * @return array|Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author FashionJune
     */
    public function getOrderBySn(string $order_sn, $field = true)
    {
        return $this->where('order_sn', $order_sn)->field($field)->find();
    }


    /**
     * @title 后台给会员充值
     * @param $post
     * @return array
     * @author FashionJune
     */
    public function rechargeByAdmin($post)
    {
        $post['money_type'] = $post['money_type'] ?? 1;
        $uid = UserBase::where('id', $post['user_id'])->value('id') ?? api_error('会员不存在');
        $money = ($post['money'] > 0) ? (float)$post['money'] : api_error('充值金额必须大于0');
//        $re = UserMoneyChange::init()->moneyInc($uid,$money,'admin_recharge');
        Db::startTrans();
        try {
            $insert_data = [
                'order_sn' => $this->create_sn(),
                'user_id' => $uid,
                'pay_time' => time(),
                'money' => $money,
                'change_type' => 31,
                'status' => 2,
            ];
            $this->save($insert_data);
            $re = UserMoneyChange::init()->moneyInc($uid, $money, 'admin_recharge');
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            return error('充值记录添加失败');
        }
        return $re['status'] ? success('充值成功') : error('充值失败：' . $re['msg']);
    }

    /**
     * @title 后台给会员扣款
     * @param $post
     * @return array
     * @author FashionJune
     */
    public function decByAdmin($post)
    {
        $post['money_type'] = $post['money_type'] ?? 1;
        $uid = UserBase::where('id', $post['user_id'])->value('id') ?? api_error('会员不存在');
        $money = ($post['money_dec'] > 0) ? (float)$post['money_dec'] : api_error('金额必须大于0');
        $re = UserMoneyChange::init()->moneyDec($uid, $money, 'admin_decmoney');
        return $re['status'] ? success('扣款成功') : error('扣款失败：' . $re['msg']);
    }

    /**
     * @title 会员充值
     * @param $uid
     * @param $money
     * @param int $money_type
     * @return array
     * @author FashionJune
     */
    public function rechargeByUser($uid, $money, $money_type = 1)
    {
        $openid = UserBase::where('id', $uid)->value('openid') ?? api_error('会员信息有误');
        $money = ($money > 0) ? (float)$money : api_error('充值金额必须大于0');
        Db::startTrans();
        try {
            $insert_data = [
                'order_sn' => $this->create_sn(),
                'user_id' => $uid,
//                'pay_time' => time(),
                'money' => $money,
                'change_type' => 21,
                'money_type' => $money_type,
                'status' => 1,
            ];
            $this->save($insert_data);
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            SystemErrorLog::init()->addError($e->getMessage());
            return error('充值记录添加失败');
        }
        return success(['openid' => $openid, 'order_sn' => $insert_data['order_sn']], '充值成功');
    }

    /**
     * @title 预付金退款流程
     * @param int $uid
     * @param float $money
     * @param int $money_type
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author FashionJune
     */
    public function refundByUser(int $uid, float $money, int $money_type = 1)
    {
        $hasmoney = UserBase::where('id', $uid)->value('has_money' . $money_type);
        if ($hasmoney < $money) {
            return error('余额不足');
        }
        $to_refund = $money;
        $map_user_recharge = [
            'user_id' => $uid,
            'status' => 2,
            'change_type' => 21
        ];
        $all_recharge_orders = $this->where($map_user_recharge)->order('id desc')->field(true)->select();
        if (!$all_recharge_orders->toArray()) {
            return error('没有待退款的订单');
        }
        $log = [];
        foreach ($all_recharge_orders as $order) {//循环将所有预付金退款
            if ($to_refund <= 0) {
                break;
            }
            $refund_money = (($to_refund - $order['money']) > 0) ? $order['money'] : $to_refund;
            $refund_sn = $this->create_sn('B');
            $re = WepayService::init()->createRefund($order['we_order_sn'], $refund_sn, $order['money'], $refund_money);
            $log[] = $re;
            if ($re['status']) {//单笔退款成功
                $to_refund = ($to_refund - $refund_money);
                //更新当前订单状态为退款中
                $order->save(['status' => 3, 'refund_sn' => $refund_sn, 'we_refund_sn' => $re['data']['we_refund_sn']]);
                //扣除用户余额
                UserMoneyChange::init()->moneyDec($order['user_id'], $refund_money, 'wechat_refund');
            } else {//某笔退款失败，继续走下一笔
                continue;
            }
        }
        return success($log, '退款成功');
    }

    /**
     * @title 会员取消付款
     * @param int $uid
     * @param string $order_sn
     * @return array
     * @author FashionJune
     */
    public function cancelRechargeByUser(int $uid, string $order_sn)
    {
        $order = $this->getOrderBySn($order_sn);
        if (!$order) {
            return error('充值订单不存在');
        } elseif ($order['user_id'] != $uid) {
            return error('非本人订单无法取消');
        }
        try {
            $order->save(['status' => -1]);
        } catch (\Exception $e) {
            Log::write('cancel_recharge_failed:' . $e->getMessage(), 'model-error');
            return error('请求失败，请稍后再试');
        }
        return success();
    }


}